<?php

namespace app\traits;

use helper\Redisearch;

/*
 * 数据表缓存 (单条,多条)
 */
trait Scout
{
    /*
     * 多条缓存
     */
    public static function setScoutAll(array $ids){
        $rows = self::whereIn('id', $ids)->field(self::$scoutField)->select()->toArray();
        if(count($rows) > 0){
            $mult = redis()->multi();
            foreach($rows as $k => $row){
                $rows[$k] = array_map(fn($v)=>is_array($v)?json_encode($v):$v, $row);
                $mult->hmset(self::$scoutIndex . ':' . $row['id'], $rows[$k]);
            }
            $mult->exec();
        }
        return $rows;
    }
    /*
     * 单个缓存
     */
    public static function setScoutOne(int $id, array $view = []) : array {
        if(empty($id)) return [];
        if(empty($view)){
            $model = self::where('id', $id)->field(self::$scoutField)->find();
            if(!$model){
                return [];
            }
            $view = $model->toArray();
        } else {
            $view = array_intersect_key($view, array_flip(self::$scoutField));
        }
        $view = array_map(fn($v)=>is_array($v)?json_encode($v):$v, $view);
        redis()->hmset(self::$scoutIndex . ':'  . $id, $view);
        return $view;
    }
    /*
     * 单条缓存
     */
    public static function one(int $id, $field = []){
        if(empty($id)) return is_string($field)? '' : [];
        $view = redis()->hgetall(self::$scoutIndex . ':'  . $id);
        empty($view) && ($view = self::setScoutOne($id));
        if(is_string($field)){
            return isset($view[$field]) ? $view[$field] : ''; 
        }
        
        if (count($field) === 0) {
            return $view;
        } else {
            return array_intersect_key($view, array_flip($field));
        }
    }
    /*
     * 多条缓存
     */
    public static function all(array $ids, array | string $field = []){
        if(count($ids) === 0) return [];
        $res = (new Redisearch)->index(self::$scoutIndex)->where('id', 'in', $ids);
        $type = is_string($field) ? 1 : (count($field) === 0 ? 2 : 3);
        if($type == 1){
            $views = $res->column($field, 'id');
        } elseif ($type == 2) {
            $views = $res->column(self::$scoutField, 'id');
        } else {
            $views = $res->column(array_intersect(self::$scoutField, $field), 'id');
        }
        $diffIds = array_diff($ids, $type == 1 ? array_keys($views) : array_column($views, 'id'));
        if(count($diffIds) > 0){
            $type == 3 && ($keys = array_flip($field));
            $rows = self::setScoutAll($diffIds);
            foreach($rows as $row){
                $views[$row['id']] = $type == 1 ? $row[$field] : ($type == 2 ? $row : array_intersect_key($row, $keys));
            }
        }
        return $views;
    }
    public static function name($id, $field = 'name'){
        return self::one($id, $field);
    }
    public static function names($ids, $field = 'name'){
        return self::all($ids, $field);
    }
    public static function scout($field, $signo = '=', $value = null){
        return (new Redisearch)->index(self::$scoutIndex)->where(...func_get_args());
    }
    // 刷新缓存
    public static function flush(){
        $rs = new Redisearch;
        $rs->drop(self::$scoutIndex);
        $rs->create(self::$scoutIndex, self::$scoutField);
        $rows = self::column(array_keys(self::$scoutField), 'id');
        array_map(fn($r)=>redis()->hmset(self::$scoutIndex . ':' . $r['id'], $r), $rows);
    }
}
